home *** CD-ROM | disk | FTP | other *** search
- /*
- File: BestFitH.h
-
- Contains: BestFitHeap class interface
-
- Owned by: Michael Burbidge
- Owned by: Jens Alfke
-
- Copyright: © 1993 - 1996 by Apple Computer, Inc., all rights reserved.
-
- Change History (most recent first):
-
- <3> 9/13/96 jpa 1371387: Deferred-coalesce optimization.
- Other speedups. 1371387: Sped up BytesFree.
- <10> 5/4/95 jpa Support for finding largest free block
- [1235657] and validating memory ranges
- [1246077]
- <9> 1/25/95 jpa Removed five-$ comments [1210981]
- <8> 10/24/94 jpa Constness [1194286]
- <7> 9/29/94 RA 1189812: Mods for 68K build.
- <6> 9/14/94 jpa Eliminated dependencies on rest of OpenDoc.
- Added support for getting the heap of a
- block by stuffing heap ptr in busy block
- header. [1186692]
- <5> 8/17/94 jpa (Oops, deleted obsolete "in progress" msg)
- <4> 8/17/94 jpa Implemented huge-block support [1179565],
- segment disposal [1181509] and the
- SOM-block flag [1181510].
- <3> 8/8/94 jpa Added fHugeBlockSize -- not used yet
- [1179565]
- <2> 6/10/94 MB Make it build
- <1> 6/9/94 MB first checked in
- <4> 5/27/94 MB #1162181: Fixed MMM integration bug
- <2> 5/9/94 MB #1162181: Changes necessary to install MMM.
- <1> 4/29/94 MB first checked in
- To Do:
- In Progress:
- */
-
- #ifndef _BESTFITH_
- #define _BESTFITH_
-
- #ifndef _MEMORYHE_
- #include "MemoryHe.h"
- #endif
-
-
- #ifdef MM_DEFER_COALESCE
- const int kAvailBlockSizeLimit = 128; // Limit of size of 'small' blocks
- const int kNAvailListsToCheck = 4; // Number of lists to look at when allocating
- #endif
-
-
- //========================================================================================
- // Forward class declarations
- //========================================================================================
-
- class PrivBestFitBlock;
- class BestFitHeap;
-
-
- //========================================================================================
- // STRUCT PrivBestFitBlockFreeListLinks
- //
- // The following fields are only present in free blocks. They are used to link the free
- // block into the free block tree. The address of a free block is also stored at the end
- // of the block and must be accounted for in the minimum block size.
- //========================================================================================
-
- struct PrivBestFitBlockFreeListLinks
- {
- PrivBestFitBlock* fParent;
- PrivBestFitBlock* fLeft;
- PrivBestFitBlock* fRight;
- };
-
-
- //========================================================================================
- // STRUCT PrivBestFitBlockHeader
- //========================================================================================
-
- // The fBits field of PrivBestFitBlockHeader contains five fields. The following masks are
- // used to get and set the fields. The block type field is used to distinguish best fit
- // blocks from chunky blocks and must be the first four bits of the last byte in fBits.
-
- #ifdef MM_LITTLE_ENDIAN
- // Bytes are in reverse order in a long.
-
- const unsigned long BestFitBlockHeader_kSizeMask = 0x00FFFFFF;
- const unsigned long BestFitBlockHeader_kSizeShift = 0;
-
- // const unsigned long BestFitBlockHeader_kBlockTypeMask = 0xC0000000;
- // const unsigned long BestFitBlockHeader_kBlockTypeShift = 30;
-
- const unsigned long BestFitBlockHeader_kAvailMask = 0x40000000;
- const unsigned long BestFitBlockHeader_kAvailShift = 30;
-
- const unsigned long BestFitBlockHeader_kIsObjectMask = 0x20000000;
- const unsigned long BestFitBlockHeader_kIsObjectShift = 29;
-
- const unsigned long BestFitBlockHeader_kFirstBlockMask = 0x10000000;
- const unsigned long BestFitBlockHeader_kFirstBlockShift = 28;
-
- const unsigned long BestFitBlockHeader_kBusyMask = 0x08000000;
- const unsigned long BestFitBlockHeader_kBusyShift = 27;
-
- const unsigned long BestFitBlockHeader_kPreviousBusyMask = 0x04000000;
- const unsigned long BestFitBlockHeader_kPreviousBusyShift = 26;
-
- const unsigned long BestFitBlockHeader_kMagicNumberMask = 0x03000000;
- const unsigned long BestFitBlockHeader_kMagicNumberShift = 24;
- #else
- const unsigned long BestFitBlockHeader_kSizeMask = 0xFFFFFF00;
- const unsigned long BestFitBlockHeader_kSizeShift = 8;
-
- const unsigned long BestFitBlockHeader_kAvailMask = 0x00000040;
- const unsigned long BestFitBlockHeader_kAvailShift = 6;
-
- // const unsigned long BestFitBlockHeader_kBlockTypeMask = 0x000000C0;
- // const unsigned long BestFitBlockHeader_kBlockTypeShift = 6;
-
- const unsigned long BestFitBlockHeader_kIsObjectMask = 0x00000020;
- const unsigned long BestFitBlockHeader_kIsObjectShift = 5;
-
- const unsigned long BestFitBlockHeader_kFirstBlockMask = 0x00000010;
- const unsigned long BestFitBlockHeader_kFirstBlockShift = 4;
-
- const unsigned long BestFitBlockHeader_kBusyMask = 0x00000008;
- const unsigned long BestFitBlockHeader_kBusyShift = 3;
-
- const unsigned long BestFitBlockHeader_kPreviousBusyMask = 0x00000004;
- const unsigned long BestFitBlockHeader_kPreviousBusyShift = 2;
-
- const unsigned long BestFitBlockHeader_kMagicNumberMask = 0x00000003;
- const unsigned long BestFitBlockHeader_kMagicNumberShift = 0;
- #endif
-
-
-
- class PrivBestFitBlockHeader
- {
- protected:
- unsigned long fBits;
- union{
- BestFitHeap* fHeap; // Busy block
- PrivBestFitBlock* fNext; // Avail block, or blocklet in free list
- struct {
- PrivBestFitBlock* fParent; // Free block in tree
- PrivBestFitBlock* fLeft;
- PrivBestFitBlock* fRight;
- } fFreeLinks;
- };
- };
-
-
- //========================================================================================
- // CLASS PrivBestFitBlock
- //========================================================================================
-
- #ifdef BUILD_WIN16
- const ODBlockSize BestFitBlock_kMaxBlockSize = 60L * 1024L;
- // Block size limited by 64K limit of far pointers. Allow 4K for overhead in the
- // various layers.
- #else
- const ODBlockSize BestFitBlock_kMaxBlockSize = 0x00FFFFFF;
- #endif
-
-
- class PrivBestFitBlock :PrivBestFitBlockHeader
- {
- public:
-
- enum
- {
- kBusyOverhead = sizeof(unsigned long) + sizeof(BestFitHeap*),
- kMinBlockSize = sizeof(PrivBestFitBlockHeader) + sizeof(void *),
- // kBlockTypeId = MemoryHeap::kBlockTypeId + 1,
- kMagicNumber = 0x3
- };
-
-
- mmboolean operator>(const PrivBestFitBlock& blk) const;
- mmboolean operator<(const PrivBestFitBlock& blk) const;
- mmboolean operator>=(const PrivBestFitBlock& blk) const;
- mmboolean operator<=(const PrivBestFitBlock& blk) const;
- mmboolean operator==(const PrivBestFitBlock& blk) const;
- mmboolean operator!=(const PrivBestFitBlock& blk) const;
-
- inline void operator delete(void *) { };
- void* operator new(SIZE_T, void* ptr);
-
- PrivBestFitBlock(int busy,
- int prevBusy,
- long size);
- PrivBestFitBlock(const PrivBestFitBlock& otherBlock);
-
- BestFitHeap* GetHeap() const;
- mmboolean GetBusy() const;
- mmboolean GetAvail() const;
- mmboolean GetIsFirst() const;
- mmboolean GetIsObject() const;
- PrivBestFitBlock* GetLeft() const;
- unsigned int GetMagicNumber() const;
- PrivBestFitBlock* GetNext() const;
- PrivBestFitBlock* GetParent() const;
- mmboolean GetPrevBusy() const;
- PrivBestFitBlock* GetRight() const;
- ODBlockSize GetSize() const;
- // unsigned short GetBlockType() const;
-
- void SetHeap(BestFitHeap*);
- void SetBusy(mmboolean busy);
- void SetAvail(mmboolean busy);
- void SetIsFirst(mmboolean first);
- void SetIsObject(mmboolean isObj);
- void SetLeft(PrivBestFitBlock* left);
- void SetNext(PrivBestFitBlock* next);
- void SetParent(PrivBestFitBlock* parent);
- void SetPrevBusy(mmboolean busy);
- void SetRight(PrivBestFitBlock* right);
- void SetSize(ODBlockSize size);
- // void SetBlockType(unsigned long blockType);
- void SetMagicNumber(unsigned long magicNumber);
-
- void StuffAddressAtEnd();
- PrivBestFitBlock* GetPrevBlock();
- PrivBestFitBlock* GetNextBlock();
-
- // PrivBestFitBlock* Coalesce( );
-
- private:
- PrivBestFitBlock& operator=(const PrivBestFitBlock& blk);//illegal
- void* operator new(SIZE_T);
- };
-
- inline void* PrivBestFitBlock::operator new(SIZE_T, void* ptr)
- {
- return ptr;
- }
-
- /*inline PrivBestFitBlock& PrivBestFitBlock::operator=(const PrivBestFitBlock& blk)
- {
- fHeader = blk.fHeader;
- return (*this);
- }*/
-
- /*inline PrivBestFitBlock::PrivBestFitBlock(const PrivBestFitBlock& blk) :
- fHeader(blk.fHeader)
- {
- }*/
-
- inline mmboolean PrivBestFitBlock::GetBusy() const
- {
- return (fBits & BestFitBlockHeader_kBusyMask) != 0;
- }
-
- inline mmboolean PrivBestFitBlock::GetAvail() const
- {
- return (fBits & BestFitBlockHeader_kAvailMask) != 0;
- }
-
- inline mmboolean PrivBestFitBlock::GetIsFirst() const
- {
- return (fBits & BestFitBlockHeader_kFirstBlockMask) != 0;
- }
-
- inline mmboolean PrivBestFitBlock::GetIsObject() const
- {
- return (fBits & BestFitBlockHeader_kIsObjectMask) != 0;
- }
-
- inline PrivBestFitBlock* PrivBestFitBlock::GetLeft() const
- {
- return fFreeLinks.fLeft;
- }
-
- inline unsigned int PrivBestFitBlock::GetMagicNumber() const
- {
- return (fBits & BestFitBlockHeader_kMagicNumberMask)
- >> BestFitBlockHeader_kMagicNumberShift;
- }
-
- inline PrivBestFitBlock* PrivBestFitBlock::GetNext() const
- {
- MM_ASSERT(!this->GetBusy() || this->GetAvail());
- return fNext;
- }
-
- inline PrivBestFitBlock* PrivBestFitBlock::GetParent() const
- {
- return fFreeLinks.fParent;
- }
-
- inline mmboolean PrivBestFitBlock::GetPrevBusy() const
- {
- return (fBits & BestFitBlockHeader_kPreviousBusyMask) != 0;
- }
-
- inline PrivBestFitBlock* PrivBestFitBlock::GetRight() const
- {
- return fFreeLinks.fRight;
- }
-
- inline ODBlockSize PrivBestFitBlock::GetSize() const
- {
- #ifdef MM_LITTLE_ENDIAN
- return (fBits & BestFitBlockHeader_kSizeMask)
- >> BestFitBlockHeader_kSizeShift;
- #else
- return fBits >> BestFitBlockHeader_kSizeShift;
- #endif
- }
-
- /*inline unsigned short PrivBestFitBlock::GetBlockType() const
- {
- return (fBits & BestFitBlockHeader_kBlockTypeMask)
- >> BestFitBlockHeader_kBlockTypeShift;
- }*/
-
- inline void PrivBestFitBlock::SetBusy(mmboolean busy)
- {
- if (busy)
- fBits |= BestFitBlockHeader_kBusyMask;
- else
- fBits &= ~BestFitBlockHeader_kBusyMask;
- }
-
- inline void PrivBestFitBlock::SetAvail(mmboolean avail)
- {
- if (avail)
- fBits |= BestFitBlockHeader_kAvailMask;
- else
- fBits &= ~BestFitBlockHeader_kAvailMask;
- }
-
- inline void PrivBestFitBlock::SetIsFirst(mmboolean first)
- {
- if (first)
- fBits |= BestFitBlockHeader_kFirstBlockMask;
- else
- fBits &= ~BestFitBlockHeader_kFirstBlockMask;
- }
-
- inline void PrivBestFitBlock::SetIsObject(mmboolean isObj)
- {
- if (isObj)
- fBits |= BestFitBlockHeader_kIsObjectMask;
- else
- fBits &= ~BestFitBlockHeader_kIsObjectMask;
- }
-
- inline void PrivBestFitBlock::SetLeft(PrivBestFitBlock* left)
- {
- fFreeLinks.fLeft = left;
- }
-
- inline void PrivBestFitBlock::SetNext(PrivBestFitBlock* next)
- {
- MM_ASSERT(!this->GetBusy() || this->GetAvail());
- fNext = next;
- }
-
- inline void PrivBestFitBlock::SetParent(PrivBestFitBlock* parent)
- {
- fFreeLinks.fParent = parent;
- }
-
- inline void PrivBestFitBlock::SetPrevBusy(mmboolean busy)
- {
- if (busy)
- fBits |= BestFitBlockHeader_kPreviousBusyMask;
- else
- fBits &= ~BestFitBlockHeader_kPreviousBusyMask;
- }
-
- inline void PrivBestFitBlock::SetRight(PrivBestFitBlock* right)
- {
- fFreeLinks.fRight = right;
- }
-
- inline void PrivBestFitBlock::SetSize(ODBlockSize size)
- {
- #ifdef MM_LITTLE_ENDIAN
- fBits &= ~BestFitBlockHeader_kSizeMask;
- fBits |= (size << BestFitBlockHeader_kSizeShift)
- & BestFitBlockHeader_kSizeMask;
- #else
- fBits = (fBits & ~BestFitBlockHeader_kSizeMask) | (size<<BestFitBlockHeader_kSizeShift);
- #endif
- }
-
- /*inline void PrivBestFitBlock::SetBlockType(unsigned long blockType)
- {
- fBits &= ~BestFitBlockHeader_kBlockTypeMask;
- fBits |= (blockType << BestFitBlockHeader_kBlockTypeShift)
- & BestFitBlockHeader_kBlockTypeMask;
- }*/
-
- inline void PrivBestFitBlock::SetMagicNumber(unsigned long magicNumber)
- {
- fBits &= ~BestFitBlockHeader_kMagicNumberMask;
- fBits |= (magicNumber << BestFitBlockHeader_kMagicNumberShift)
- & BestFitBlockHeader_kMagicNumberMask;
- }
-
- inline BestFitHeap* PrivBestFitBlock::GetHeap() const
- {
- MM_ASSERT(this->GetBusy() && !this->GetAvail());
- return fHeap;
- }
-
- inline void PrivBestFitBlock::SetHeap(BestFitHeap *heap)
- {
- MM_ASSERT(this->GetBusy() && !this->GetAvail());
- fHeap = heap;
- }
-
- inline mmboolean PrivBestFitBlock::operator>(const PrivBestFitBlock& blk) const
- {
- if (GetSize() == blk.GetSize())
- return this > &blk;
- else
- return GetSize() > blk.GetSize();
- }
-
- inline mmboolean PrivBestFitBlock::operator<(const PrivBestFitBlock& blk) const
- {
- if (GetSize() == blk.GetSize())
- return this < &blk;
- else
- return GetSize() < blk.GetSize();
- }
-
- inline mmboolean PrivBestFitBlock::operator==(const PrivBestFitBlock& blk) const
- {
- return /*GetSize() == blk.GetSize() &&*/ this == &blk;
- }
-
- inline mmboolean PrivBestFitBlock::operator>=(const PrivBestFitBlock& blk) const
- {
- return *this > blk || *this == blk;
- }
-
- inline mmboolean PrivBestFitBlock::operator<=(const PrivBestFitBlock& blk) const
- {
- return *this < blk || *this == blk;
- }
-
- inline mmboolean PrivBestFitBlock::operator!=(const PrivBestFitBlock& blk) const
- {
- return !(*this == blk);
- }
-
- inline void PrivBestFitBlock::StuffAddressAtEnd()
- {
- // coalescence possible in constant time.
-
- if (!this->GetBusy())
- {
- void** addr= (void**) ((ODBytePtr) this + this->GetSize() - sizeof(PrivBestFitBlock *));
- *addr = this;
- }
- #if MM_DEBUG
- else
- MM_WARN("PrivBestFitBlock::StuffAddressAtEnd: corrupt heap!");
- #endif
- }
-
- inline PrivBestFitBlock* PrivBestFitBlock::GetPrevBlock( )
- {
- MM_ASSERT(!this->GetPrevBusy());
- return *(PrivBestFitBlock **) ((ODBytePtr) this - sizeof(ODBlockSize));
- }
-
- inline PrivBestFitBlock* PrivBestFitBlock::GetNextBlock( )
- {
- return (PrivBestFitBlock*) ((ODBytePtr) this + this->GetSize());
- }
-
-
- //----------------------------------------------------------------------------------------
- // PrivBestFitBlock::PrivBestFitBlock
- //----------------------------------------------------------------------------------------
-
- inline PrivBestFitBlock::PrivBestFitBlock(int busy,
- int previousBusy,
- long size)
- {
- fBits = ((size << BestFitBlockHeader_kSizeShift) & BestFitBlockHeader_kSizeMask)
- | (kMagicNumber << BestFitBlockHeader_kMagicNumberShift);
-
- // Directly initializing fBits (above) has the effect of all of the following:
- // SetSize(size);
- // SetIsFirst(false);
- // SetIsObject(false);
- // SetBlockType(kBlockTypeId);
- // SetMagicNumber(kMagicNumber);
- // SetAvail(false);
-
- if( previousBusy )
- SetPrevBusy(true);
-
- if (busy)
- SetBusy(true);
- else {
- SetParent(NULL);
- SetRight(NULL);
- SetLeft(NULL);
- this->StuffAddressAtEnd();
- }
- }
-
-
- //========================================================================================
- // CLASS PrivBestFitSegment
- //
- // The BestFitHeap allocates memory from the system in segments. The segments are
- // linked together in a list so that when the heap is destroyed all segments can be
- // freed.
- //
- //========================================================================================
-
- class PrivBestFitSegment
- {
- public:
-
- friend BestFitHeap;
-
- enum
- {
- kSegmentPrefixSize = 12,
- kSegmentSuffixSize = 4,
- kSegmentOverhead = kSegmentPrefixSize + kSegmentSuffixSize
- };
-
- mmboolean AddressInSegment(const void* ptr);
- mmboolean CheckSegment( HeapWalkProc, void *refCon,
- ODBlockSize blockHeaderSize, ODBlockSize sizeDelta );
- mmboolean Coalesce( BestFitHeap*, mmboolean &coalescence );
-
- #if MM_DEBUG
- mmboolean FindBlockContaining( const void *start, const void *end,
- const void* &blockStart, const void* &blockEnd ) const;
- #endif
-
- private:
- void *fSegmentSpace;
- unsigned long fSegmentSize;
- PrivBestFitSegment *fNextSegment;
-
- PrivBestFitSegment(const PrivBestFitSegment& blk);
- PrivBestFitSegment& operator=(const PrivBestFitSegment& blk);
- // This class shouldn't be copied.
- };
-
- //----------------------------------------------------------------------------------------
- // INLINES PrivBestFitSegment
- //----------------------------------------------------------------------------------------
-
- inline mmboolean PrivBestFitSegment::AddressInSegment(const void* ptr)
- {
- return ptr >= fSegmentSpace &&
- ptr <= (void*) ((ODBytePtr) fSegmentSpace + fSegmentSize);
- }
-
-
- //========================================================================================
- // CLASS PrivFreeBlockTree
- //
- // Binary tree for storing free blocks. Dependent on the structure and
- // implementation of PrivBestFitBlock.
- //
- //========================================================================================
-
- class PrivFreeBlockTree
- {
- public:
- PrivFreeBlockTree();
- PrivFreeBlockTree(const PrivFreeBlockTree& blk);
-
- PrivFreeBlockTree& operator=(const PrivFreeBlockTree& blk);
-
- void AddBlock(PrivBestFitBlock* blk);
- void TreeInfo(unsigned long& bytesFree,
- unsigned long& numberOfNodes) const;
- void RemoveBlock(PrivBestFitBlock* blk);
- PrivBestFitBlock* SearchForBlock(ODBlockSize size,
- void* blk,
- PrivBestFitBlock** insertLeaf = NULL);
- const PrivBestFitBlock* FindLargestBlock( ) const;
-
- #if MM_DEBUG
- void CheckTree() const;
- void PrintTree() const;
- #endif
-
- protected:
- PrivBestFitBlock* GetSuccessorBlk(PrivBestFitBlock* blk);
- void TreeInfoHelper(PrivBestFitBlock* blk,
- unsigned long& bytesFree,
- unsigned long& numberOfNodes) const;
-
- #if MM_DEBUG
- void CheckTreeHelper(PrivBestFitBlock* blk) const;
- void PrintTreeHelper(PrivBestFitBlock* blk,
- int level = 0) const;
- #endif
-
- private:
- PrivBestFitBlock fRoot;
-
- };
-
-
- //========================================================================================
- // CLASS PrivFreeBlockList
- //
- // Linked list of free blocks. Used for small blocks that can't hold tree nodes.
- //
- //========================================================================================
-
- class PrivFreeBlockList
- {
- public:
- PrivFreeBlockList( ) {fFirst=NULL;}
-
- long NotEmpty( ) {return fFirst!=NULL;}
- PrivBestFitBlock* First( ) {return fFirst;}
- void ForceEmpty( ) {fFirst = NULL;}
- void ForceFirst( PrivBestFitBlock *f ) {fFirst = f;}
-
- PrivBestFitBlock* GetBlock( ); // do not call on empty list
- void AddBlock( PrivBestFitBlock *b );
-
- private:
- PrivBestFitBlock *fFirst; // First block, or NULL if list is empty
- PrivBestFitBlock *fLast; // Last block. Invalid if list is empty.
- };
-
- inline PrivBestFitBlock*
- PrivFreeBlockList::GetBlock( )
- {
- PrivBestFitBlock *b = fFirst;
- fFirst = fFirst->GetNext();
- return b;
- }
-
- inline void
- PrivFreeBlockList::AddBlock( PrivBestFitBlock *b )
- {
- b->SetNext(NULL);
- if( fFirst )
- fLast->SetNext(b);
- else
- fFirst = b;
- fLast = b;
- }
-
-
- //========================================================================================
- // CLASS BestFitHeap
- //
- // Memory allocation heap using the best fit allocation strategy.
- //
- //========================================================================================
-
- class BestFitHeap : public MemoryHeap
- {
- public:
-
- virtual unsigned long BytesFree() const {return fFreeBytes+fAvailBytes;}
- virtual unsigned long HeapSize() const;
-
- BestFitHeap(unsigned long sizeInitial,
- unsigned long sizeIncrement = 0,
- unsigned long hugeBlockSize = 0, // "0" means sizeIncrement/2
- MMHeapLocation = kMMTempMemory);
- virtual ~BestFitHeap();
-
- void IBestFitHeap();
- void ExpandHeap(unsigned long sizeInitial, unsigned long sizeIncrement);
-
- long GetSizeIncrement( ) {return fSizeIncrement;}
- long GetHugeBlockSize( ) {return fSizeIncrement;}
-
- #ifdef MM_DEFER_COALESCE
- void Coalesce() {this->Coalesce(BestFitBlock_kMaxBlockSize);}
- PrivBestFitBlock* Coalesce( ODBlockSize sizeNeeded );
- #endif
-
- #if MM_DEBUG
- virtual void Check( HeapWalkProc proc =NULL, void *refCon =NULL ) const;
- virtual mmboolean IsMyBlock(const void* blk) const;
- virtual void Print(char* msg = "") const;
- #endif
-
- protected:
-
- void AddToFreeBlocks(PrivBestFitBlock* blk);
- PrivBestFitBlock* BasicFreeBlock( PrivBestFitBlock* );
- PrivBestFitBlock* CreateNewSegment(unsigned long size); //returns free block --jpa
- mmboolean DeleteSegmentIfEmpty( PrivBestFitBlock *blk );
- void DeleteSegment( PrivBestFitSegment *seg );
- void DeleteSegments();
- void GrowHeap(unsigned long sizeIncrement);
- void RemoveFromFreeBlocks(PrivBestFitBlock* blk);
- PrivBestFitBlock* SearchFreeBlocks(ODBlockSize size);
-
- virtual void* DoAllocate(ODBlockSize size, ODBlockSize& allocatedSize);
- virtual ODBlockSize DoBlockSize(const void* block) const;
- virtual void DoFree(void*);
- // virtual void DoReset();
- virtual unsigned long DoLargestFreeBlock() const;
-
- virtual void DoSetBlockIsObject( void* ptr, mmboolean isObject );
-
- virtual mmboolean DoBlockIsObject( const void* ptr ) const;
-
- virtual MemoryHeap* DoGetBlockHeap( const void* ) const;
-
- #if MM_DEBUG
- virtual void CompilerCheck();
- virtual mmboolean DoIsValidBlock(const void* blk) const;
- mmboolean DoFindBlockContaining( const void *start, const void *end,
- const void* &blockStart, const void* &blockEnd ) const;
- #endif
-
- private:
- void AddFreeBytes( long n )
- #if MM_DEBUG_COALESCE
- ;
- #else
- {fFreeBytes += n;}
- #endif
-
- PrivBestFitSegment* fSegments;
- unsigned long fSizeIncrement;
- unsigned long fSizeInitial;
- unsigned long fHugeBlockSize;
- ODBlockSize fFreeBytes;
- ODBlockSize fAvailBytes; // Size of blocks in avail lists
- PrivFreeBlockTree fFreeTree;
-
- #ifdef MM_DEFER_COALESCE
- enum{
- // We need a list for every multiple of 4 bytes over the minimum size.
- // The block-size limit needs to be translated into physical sizes (+overhead).
- // And leave extra blocks at end so we don't fall off the end while searching.
- kNAvailBlockLists = ((kAvailBlockSizeLimit+PrivBestFitBlock::kBusyOverhead
- -PrivBestFitBlock::kMinBlockSize) >>2)
- };
- PrivFreeBlockList fAvailBlocks[kNAvailBlockLists + kNAvailListsToCheck-1];
- #endif
-
- enum{ kMaxHugeBlockSize = 65535L };
-
- BestFitHeap(const BestFitHeap& blk);
- BestFitHeap& operator=(const BestFitHeap& blk);
- // This class shouldn't be copied.
-
- friend mmboolean PrivBestFitSegment::Coalesce( BestFitHeap*,mmboolean& );
- };
-
-
- //----------------------------------------------------------------------------------------
- // BestFitHeap::AddToFreeBlocks
- //----------------------------------------------------------------------------------------
-
- inline void BestFitHeap::AddToFreeBlocks(PrivBestFitBlock* blk)
- {
- fFreeTree.AddBlock(blk);
- this->AddFreeBytes(blk->GetSize());
- }
-
- //----------------------------------------------------------------------------------------
- // BestFitHeap::RemoveFromFreeBlocks
- //----------------------------------------------------------------------------------------
-
- inline void BestFitHeap::RemoveFromFreeBlocks(PrivBestFitBlock* blk)
- {
- fFreeTree.RemoveBlock(blk);
- this->AddFreeBytes(-blk->GetSize());
- }
-
- //----------------------------------------------------------------------------------------
- // BestFitHeap::SearchFreeBlocks
- //----------------------------------------------------------------------------------------
-
- inline PrivBestFitBlock* BestFitHeap::SearchFreeBlocks(ODBlockSize size)
- {
- return fFreeTree.SearchForBlock(size, NULL, NULL);
- }
-
- #endif
-